
const myPromise = (arg, timeout = 100) => {
    return new Promise(resolve => {
        setTimeout(() => {
            if (typeof arg === 'function') {
                arg()
            } else {
                console.log(arg)
            }
            resolve()
        }, timeout)

    })
}

exports.callback = function () {
    return myPromise(() => {
        console.log('heheda')
    })
}

// Generator 函数
const func = function* () {
    console.log('first')
    yield '1'
    console.log('second')
    yield '2'
    console.log('third')
    yield '3'
}

// let fn = func()
// console.log('next: ', fn.next())
// console.log('next: ', fn.next())
// console.log('next: ', fn.next())

// 或者迭代器 建议用下面的generator

// for (let item of func()) {

// }

exports.generator = () => {
    /**
     * @param {*} name  严格异步执行
     */
    const generator = function* (name) {
        yield myPromise(name + 1)
        yield myPromise(name + 2)
        yield myPromise(name + 3)
    }
    /**
     * 含金量较高代码
     * @param {*} generator function*
     */
    const co = generator => {
        if (it = generator.next().value) {
            it.then(res => {
                co(generator)
            })
        } else {
            return
        }
    }
    co(generator('wilsunson handsome'))
}

/**
 *  async/await 是es7提出的终极异步解决方案
 *  任何await 语句后面的Promise对象变成reject状态，整个async函数都会中断执行
 *  async函数内部的Promise函数执行完才执行.then
 */
exports.asyncAwait = async () => {
    await myPromise('赶紧学习拉开差距')
    await myPromise('正在学习请勿打扰')
    await myPromise('学习使我快乐')
}

/**
 * 事件监听方式
 * 采用事件驱动模式，不取决于执行顺序，取决于某些事是否发生，有点像Vue的emit
 */
exports.event = async () => {
    const asyncFun = name => event => {
        setTimeout(() => {
            console.log(name)
            event.emit('fnEnd')
        }, 100)
        return event
    }
    const ary = [
        asyncFun('handsome boy1'),
        asyncFun('handsome boy2'),
        asyncFun('handsome boy3')
    ]
    const { EventEmitter } = require('events')
    const event = new EventEmitter()
    let i = 0
    event.on('fnEnd', ()=> i<ary.length && ary[i++](event)) // 第一次走，i===0
    event.emit('fnEnd')
}
